<!--
 * @Descripttion: 
 * @Author: Kevin
 * @Date: 2022-06-14 10:58:57
 * @LastEditors: Tommy Chen
 * @LastEditTime: 2024-06-27
-->
<template>
  <div>
    <div class="mapping-policy-wrapper">
      <a-form-model
        style="width: 800px"
        :labelCol="{ span: 8 }"
        :wrapperCol="{ span: 16 }"
        labelAlign="left"
        :model="mappingPolicyForm"
        ref="mappingPolicyFormRef"
        :rules="formRuleObj"
        :colon="false"
      >
        <a-form-model-item :label="$t('thirdPart.adAreaType')">
          <a-radio-group v-model="mappingPolicyForm.syncType">
            <a-radio value="ou"> {{ $t('thirdPart.ou') }} </a-radio>
            <a-radio value="group"> {{ $t('thirdPart.group') }} </a-radio>
          </a-radio-group>
        </a-form-model-item>
        <a-form-model-item prop="groupRank" :label="$t('thirdPart.syncRank')">
          <a-input-number
            style="width: 120px"
            v-model="mappingPolicyForm.syncLevel"
            :min="1"
            :max="3"
          />
        </a-form-model-item>
      </a-form-model>
      <div class="btn-wrapper">
        <a-button ghost type="primary" @click="onSync">
          {{ $t('thirdPart.syncGroup') }}
        </a-button>
        <a-button ghost type="primary" @click="onReset">
          {{ $t('thirdPart.reset') }}
        </a-button>
      </div>
      <div v-show="isToReset" class="opt-tip">
        {{ $t('thirdPart.resetTip') }}
      </div>
    </div>
    <rj-table
      rowKey="name"
      :columns="mappingColumns"
      :data-source="mappingTree"
      :expanded-row-keys.sync="expandedRowKeys"
      @expand="onExpand"
      class="mapping-table"
    >
      <template slot="authPolicy" slot-scope="text, record">
        <a-select
          v-if="record.dn"
          allowClear
          style="width: 320px"
          v-model="record.profileId"
          @change="onChangeProfileId"
        >
          <icon-font type="ic-tree-device" slot="menuItemSelectedIcon" />
          <a-select-option
            v-for="item in authPolicys"
            :key="item.uuid"
            :title="item.name"
          >
            {{ item.name }}
          </a-select-option>
        </a-select>
      </template>
    </rj-table>
    <div style="margin-top: 24px">
      <a-button type="primary" @click="onSave">
        {{ $t('common.save') }}
      </a-button>
    </div>
  </div>
</template>

<script>
import LayoutPanel from '@views/common/deviceDetail/components/components/layoutPanel.vue';
import { mapState } from 'vuex';
import authSysMixin from '@project/authSys/mixin/authSysMixin';
import { requestHttp, maccApi } from '@utils/index';
import { RjTable } from '@components';
import _ from 'lodash';
import i18n from '@/locales';
import { tree } from 'd3';

const mappingColumns = [
  {
    title: i18n.t('thirdPart.groupName'),
    dataIndex: 'name',
  },
  {
    title: i18n.t('thirdPart.authPolicy'),
    dataIndex: 'authPolicy',
    width: '60%',
    scopedSlots: { customRender: 'authPolicy' },
    align: 'left',
  },
];

export default {
  name: 'mappingForm',
  mixins: [authSysMixin],
  components: {
    'rj-table': RjTable,
  },
  props: {
    record: {
      typeof: Object,
      default: () => {
        return null;
      },
    },
  },
  data() {
    return {
      // data,
      // columns,
      // expandedRowKeys2: [],
      isToReset: false,
      mappingColumns,
      mappingPolicyForm: {
        syncType: 'ou',
        syncLevel: 3,
      },
      expandedRowKeys: [], // 初始可以设置为空数组，或加载后设置所有行key
      mappingTree: [],
      originalMapping: {}, // tommy 24.6.26 为了让切换跟组的时候配置不改变
      formRuleObj: {
        syncType: [
          {
            required: true,
            message: this.$t('common.mustEnter'),
            trigger: 'change',
          },
        ],
        syncLevel: [
          {
            validator: (rule, value, callback) => {
              let num = Number(value);
              if (!/(^[1-9]([0-9]*)$|^[0-9]$)/.test(value)) {
                return callback(new Error(this.$t('common.onlyInt')));
              }
              if (1 <= num && num <= 10) {
                return callback();
              } else {
                return callback(
                  new Error(this.$t('common.rangeCustom', [1, 10]))
                );
              }
            },
            trigger: 'blur',
          },
        ],
      },
    };
  },
  watch: {
    record: {
      handler(value) {
        if (value) {
          const tempForm = _.cloneDeep(value);
          this.mappingPolicyForm.syncType = tempForm.syncType || 'ou';
          this.mappingPolicyForm.syncLevel = tempForm.syncLevel || 3;

          // tommy 根节点根据不同类型显示不同名称
          let rootName = tempForm.serverDomain;
          if (tempForm.type === 'ldap') {
            rootName = tempForm.rootDn;
          }
          this.mappingTree = [
            {
              name: rootName,
              children: tempForm.accountSourceProfileList,
            },
          ];
          this.loopOverTree(this.mappingTree[0]);

          this.setOriginalMapping(); // tommy 初始化时设置下初始数据，更新组织时可用来匹配
        }
      },
      deep: true,
      immediate: true,
    },
  },
  computed: {
    ...mapState('AuthCommon', ['authPolicys', 'sourceForm']),
  },
  mounted() {},
  methods: {
    setOriginalMapping() {
      const originalMappings = [];
      this.loopOverTreeHasPolicy(this.mappingTree[0], originalMappings);
      this.originalMapping = {};
      originalMappings.forEach((item) => {
        this.originalMapping[item.dn] = item.profileId;
      });
    },
    onChangeProfileId() {
      this.isToReset = false;
    },
    onReset() {
      const self = this;
      this.$confirm({
        content: this.$t('thirdPart.resetConfirm'),
        centered: true,
        onOk: () => {
          self.isToReset = true;
          self.loopOverTreeReset(self.mappingTree[0]);
        },
      });
    },

    loopOverTreeReset(treeData) {
      // console.log('loop ' + treeData.name);
      this.$set(treeData, 'profileId', undefined);
      if (treeData.children) {
        treeData.children.forEach((child) => {
          this.loopOverTreeReset(child);
        });
      }
    },

    isNumber(val) {
      return _.isNumber(val);
    },

    onSave() {
      self.isToReset = false;
      this.setOriginalMapping();
      this.$emit('saveForm');
    },
    onExpand(expanded, record) {
      if (expanded) {
        this.expandedRowKeys.push(record.name);
      } else {
        this.expandedRowKeys = this.expandedRowKeys.filter(
          (item) => item !== record.name
        );
      }
    },

    getSourceForm() {
      this.mappingTree = [
        {
          name: this.sourceForm.serverDomain,
        },
      ];
      if (this.mappingTree.length > 0) {
        this.loopOverTree(this.mappingTree[0]);
      }
    },

    getModel() {
      return new Promise((resolve) => {
        const mappingPolicys = [];
        this.loopOverTreeHasPolicy(this.mappingTree[0], mappingPolicys);

        this.mappingForm = {
          groupId: this.groupId,
          type: this.sourceForm.type,
          name: this.sourceForm.name,
          serverDomain: this.sourceForm.serverDomain,
          serverIp: this.sourceForm.serverIp,
          serverPort: this.sourceForm.serverPort,
          rootDn: this.sourceForm.rootDn,
          adminName: this.sourceForm.adminName,
          adminPwd: this.sourceForm.adminPwd,
          syncType: this.mappingPolicyForm.syncType,
          syncLevel: this.mappingPolicyForm.syncLevel,
          accountSourceProfileList: mappingPolicys,
        };
        if (this.sourceForm.type === 'ldap') {
          this.mappingForm.serverIp = this.sourceForm.ldapIp;
          this.mappingForm.serverPort = this.sourceForm.ldapPort;
        }

        resolve(this.mappingForm);
      });
    },

    /**
     * @description: 遍历树让树节点展开，
     * @param {*} treeData
     * @param {*} paramObj
     *              isSync 是否是同步分组结构，这种情况根据已有配置重新设置profileId
     * @return {*}
     */
    loopOverTree(treeData, paramObj = { isSync: false }) {
      const { isSync } = paramObj;
      // console.log('loop ' + treeData.name);

      if (isSync) {
        const profileId = this.originalMapping[treeData.dn];
        if (profileId) {
          this.$set(treeData, 'profileId', profileId);
        }
      }
      if (treeData.children) {
        this.expandedRowKeys.push(treeData.name);
        treeData.children.forEach((child) => {
          this.loopOverTree(child, paramObj);
        });
      }
    },

    loopOverTreeHasPolicy(treeData, policys) {
      // console.log('loop ' + treeData.name);
      if (treeData.profileId) {
        policys.push({
          name: treeData.name,
          profileId: treeData.profileId,
          level: treeData.level,
          dn: treeData.dn,
        });
      }
      if (treeData.children) {
        treeData.children.forEach((child) => {
          this.loopOverTreeHasPolicy(child, policys);
        });
      }
    },

    async onSync() {
      const sourceForm = this.sourceForm;
      const paramObj = {
        type: sourceForm.type,
        serverDomain: sourceForm.serverDomain,
        serverIp: sourceForm.serverIp,
        serverPort: sourceForm.serverPort,
        adminName: sourceForm.adminName,
        adminPwd: sourceForm.adminPwd,
        syncType: this.mappingPolicyForm.syncType,
        syncLevel: this.mappingPolicyForm.syncLevel,
      };
      if (sourceForm.type === 'ldap') {
        paramObj.rootDn = sourceForm.rootDn;
        paramObj.serverIp = sourceForm.ldapIp;
        paramObj.serverPort = sourceForm.ldapPort;
      }

      const res = await this.requestHttpAuth({
        api: maccApi.MACC_SOURCE_SYNC_POST_API,
        method: 'POST',
        params: paramObj,
      });

      if (res.data.success) {
        const trees = res.data.result;
        let rootName = sourceForm.serverDomain;
        if (sourceForm.type === 'ldap') {
          rootName = sourceForm.rootDn;
        }
        const root = {
          name: rootName,
          children: trees,
        };
        this.mappingTree = [root];
        this.loopOverTree(this.mappingTree[0], { isSync: true });
        this.$message.success(this.$t('thirdPart.syncSuccess'));
      } else {
        this.$message.warning(res.data.message);
      }
    },
  },
};
</script>

<style lang="less" scoped>
@import url('@/project/authSys/assets/skin/common.less');
/deep/.ant-form-item {
  margin-bottom: 8px;
}
.list-group-item {
  display: flex;
  max-width: 1200px;
  border-bottom: 1px solid @table-border;
  position: relative;
  background-color: #fff;
  > div {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .icon-wrapper {
    padding: 16px;
    cursor: move;
    i {
      font-size: 16px;
    }
  }
  .item-wrapper {
    padding: 8px 16px;
    flex: 1;
    .ant-form-item {
      flex: 1;
    }
    .w-120 {
      width: 120px;
      flex: none;
    }
  }
  .policy-wrapper {
    padding: 8px 16px;
  }
}
.w-250 {
  width: 250px;
}
.error-icon {
  color: @error-color;
}
.mapping-header {
  background: @bg-component;
  border-bottom: 1px solid @component-stroke;
  height: 40px;
  max-width: 1200px;
  display: flex;
  align-items: center;
}
.form-item-tip {
  color: #8c8c8c;
  white-space: nowrap;
}
.mapping-policy-wrapper {
  background: @bg-component;
  padding: 12px;
  max-width: 1100px;
  // .ant-form {
  //   display: flex;
  //   max-width: 1100px;
  // }
  .ant-form-item {
    flex: 1;
  }
  .btn-wrapper {
    margin-top: 12px;
    gap: 12px;
    display: flex;
  }
  /deep/.ant-form-item {
    margin-top: 12px;
    margin-bottom: 0;
  }
}
.mapping-table {
  max-width: 1100px;
  margin-top: 16px;
}
.opt-tip {
  margin-top: 8px;
  font-size: 12px;
  color: @error-color;
}
</style>
